﻿using System.Linq;
using System.Windows;
using System.Windows.Media;
using Telerik.Windows.Documents.Fixed.Model.Data;
using PdfColors = Telerik.Windows.Documents.Fixed.Model.ColorSpaces;

namespace Com.Lancetinc.Evs.Reports.RadPdf;

internal static class PdfColorHelper
{
    internal static PdfColors.ColorBase ConvertBrush(Brush brush, double opacity, IPosition position, double width,
        double height)
    {
        if (brush is SolidColorBrush solidBrush)
        {
            return ConvertSolidColorBrush(solidBrush, opacity);
        }

        if (brush is LinearGradientBrush linearGradientBrush)
        {
            return ConvertLinearGradientBrush(linearGradientBrush, opacity, position, width, height);
        }

        if (brush is RadialGradientBrush radialGradientBrush)
        {
            return ConvertRadialGradientBrush(radialGradientBrush, opacity, position, width, height);
        }

        return null;
    }

    internal static PdfColors.RgbColor ConvertSolidColorBrush(SolidColorBrush brush, double opacity)
    {
        return new PdfColors.RgbColor((byte)(brush.Color.A * opacity), brush.Color.R, brush.Color.G, brush.Color.B);
    }

    internal static PdfColors.LinearGradient ConvertLinearGradientBrush(LinearGradientBrush brush, double opacity,
        IPosition position, double width, double height)
    {
        var startPoint = new Point(brush.StartPoint.X * width, brush.StartPoint.Y * height);
        var endPoint = new Point(brush.EndPoint.X * width, brush.EndPoint.Y * height);

        var pdfGradient = new PdfColors.LinearGradient(startPoint, endPoint);
        pdfGradient.Position = position;

        foreach (var gradientStop in brush.GradientStops.OrderBy(x => x.Offset))
        {
            var rgbColor = new PdfColors.RgbColor((byte)(gradientStop.Color.A * opacity), gradientStop.Color.R,
                gradientStop.Color.G, gradientStop.Color.B);
            pdfGradient.GradientStops.Add(new PdfColors.GradientStop(rgbColor, gradientStop.Offset));
        }

        return pdfGradient;
    }

    internal static PdfColors.RadialGradient ConvertRadialGradientBrush(RadialGradientBrush brush, double opacity,
        IPosition position, double width, double height)
    {
        if (width * height == 0)
        {
            return null;
        }

        var center1 = new Point(brush.GradientOrigin.X * height, brush.GradientOrigin.Y * height);
        var center2 = new Point(brush.Center.X * height, brush.Center.Y * height);
        var pdfGradient = new PdfColors.RadialGradient(center1, center2, 0, height / 2);

        var matrix = new Matrix(width / height, 0, 0, 1, 0, 0);
        var newMatrix = matrix = MathHelper.Multiply(position.Matrix, matrix);
        pdfGradient.Position = new MatrixPosition(newMatrix);

        foreach (var gradientStop in brush.GradientStops)
        {
            var rgbColor = new PdfColors.RgbColor((byte)(gradientStop.Color.A * opacity), gradientStop.Color.R,
                gradientStop.Color.G, gradientStop.Color.B);
            pdfGradient.GradientStops.Add(new PdfColors.GradientStop(rgbColor, gradientStop.Offset));
        }

        return pdfGradient;
    }
}